package cn.leaf.calculator.engine;

import cn.hutool.core.util.NumberUtil;

import cn.leaf.calculator.bean.CalResultEntity;
import cn.leaf.calculator.bean.ParameterEntity;
import cn.leaf.calculator.resolver.FormulaBeanDefinitionResolver;
import cn.leaf.calculator.resolver.SpELFormulaBeanResolver;
import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.math.BigDecimal;
import java.util.Collection;

/**
 * SpEL（Spring Expression Language)公式计算引擎
 *
 * @author 李克国
 * @version 1.0.0
 */
@Slf4j
public class SpELFormulaCalEngine<T> implements FormulaCalEngine<T> {

    private final ExpressionParser parser;

    private FormulaBeanDefinitionResolver<T> resolver;

    public SpELFormulaCalEngine() {
        parser = new SpelExpressionParser();
        resolver = new SpELFormulaBeanResolver<>();
    }

    @Override
    public CalResultEntity execute(String formula, Collection<ParameterEntity> params) {
        Expression expression = parser.parseExpression(formula, new TemplateParserContext());
        EvaluationContext evaluationContext = new StandardEvaluationContext();
        for (ParameterEntity param : params) {
            evaluationContext.setVariable(param.getId(), param.getValue());
        }
        CalResultEntity resultEntity = new CalResultEntity();
        resultEntity.setFormula(formula);
        Object value = expression.getValue(evaluationContext);

        if (value == null || NumberUtil.isNumber(value.toString())) {
            resultEntity.setCalExpression(formula);
            resultEntity.setResult(value == null ? BigDecimal.ZERO : NumberUtil.toBigDecimal(value.toString()));
            resultEntity.setMessage("纯数字计算，公式中无变量");
            log.debug("formula:{},result {}", formula, value);
            return resultEntity;
        }
        Object value2 = parser.parseExpression(value.toString()).getValue();
        if (value2 == null) {
            resultEntity.setCalExpression(value.toString());
            resultEntity.setResult(BigDecimal.ZERO);
            resultEntity.setMessage("计算结果为空");
            log.debug("formula:{},result {}", formula, null);
            return resultEntity;
        }
        resultEntity.setCalExpression(value.toString());
        resultEntity.setResult(NumberUtil.toBigDecimal(value2.toString()));
        resultEntity.setMessage("正常计算");
        log.debug("formula:{},result {}", formula, value);
        return resultEntity;
    }

    @Override
    public FormulaBeanDefinitionResolver<T> getResolver() {
        return resolver;
    }

    @Override
    public void setResolver(FormulaBeanDefinitionResolver<T> resolver) {
        this.resolver = resolver;
    }
}
